﻿using PHMEE.Admin.Application.Contracts.DTOs.MqttDtos.Sensors;
using PHMEE.ToolKits;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
using static PHMEE.PHMEEAdminPermissions;

namespace PHMEE.Admin
{
    public class SensorAppService : PHMEEAdminAppService, ISensorAppService
    {

        private ISensorRepository _sensorRepository;
        private ISysParaRepository _sysParaRepository;
        private IVibChannelParaRepository _vibChannelRepository;
        private IPointRepository _pointRepository;
        private IRepository<Component, Guid> _componentRepository;
        private IRepository<Equipment, Guid> _equipmentRepository;
        private IRepository<Unit, Guid> _unitRepository;

        public SensorAppService(ISensorRepository sensorRepository, ISysParaRepository sysParaRepository, IVibChannelParaRepository vibChannelRepository, IPointRepository pointRepository, IRepository<Component, Guid> componentRepository, IRepository<Equipment, Guid> equipmentRepository, IRepository<Unit, Guid> unitRepository)
        {
            _sensorRepository = sensorRepository;
            _sysParaRepository = sysParaRepository;
            _vibChannelRepository = vibChannelRepository;
            _pointRepository = pointRepository;
            _componentRepository = componentRepository;
            _equipmentRepository = equipmentRepository;
            _unitRepository = unitRepository;
        }
        /// <summary>
        /// 获取传感器状态信息
        /// </summary>
        /// <param name="pageSensorDto"></param>
        /// <returns></returns>
        public async Task<List<SensorResultDto>> GetSensorsWithSensorAsync(PageSensorDto pageSensorDto)
        {
            var sensorQuery = await _sensorRepository.GetQueryableAsync();
            var sysParaQuery = await _sysParaRepository.GetQueryableAsync();
            var vibChannelQuery = await _vibChannelRepository.GetQueryableAsync();
            var pointQuery = await _pointRepository.GetQueryableAsync();
            var componentQuery = await _componentRepository.GetQueryableAsync();
            var equipmentQuery = await _equipmentRepository.GetQueryableAsync();
            var unitQuery = await _unitRepository.GetQueryableAsync();

            var query = from sensor in sensorQuery
                        join sysPara in sysParaQuery on sensor.CollectCode equals sysPara.CollectorCode
                        join vibChannel in vibChannelQuery on new { SysParaID = sysPara.Id, ChNo = sensor.ChnoId }
                                                              equals new { vibChannel.SysParaID, vibChannel.ChNo }
                        join point in pointQuery on vibChannel.PointId equals point.Id
                        where sensor.CheckType == 2
                        select new
                        {
                            point,
                            sensor,
                            vibChannel,
                            sensor.CollectCode,
                            SensorStatus = (sensor.CheckValue >= 9 && sensor.CheckValue <= 14) ? SensorStatusEnum.Normal :
                                    (sensor.CheckValue < 1) ? SensorStatusEnum.ShortCircuit :
                                    (sensor.CheckValue > 19) ? SensorStatusEnum.OpenCircuit :
                                    SensorStatusEnum.Damaged
                        };

            if (pageSensorDto.UnitId.HasValue)
            {
                query = query.Where(item =>
                (item.point.OwnerType == nameof(Unit) && item.point.OwnerId == pageSensorDto.UnitId.Value) ||// 测点挂在机组
                (item.point.OwnerType == nameof(Equipment) &&
                equipmentQuery.Any(e => e.Id == item.point.OwnerId && e.UnitId == pageSensorDto.UnitId.Value)) || // 测点挂在设备
                (item.point.OwnerType == nameof(Component) &&
                componentQuery.Any(c => c.Id == item.point.OwnerId &&
                                     equipmentQuery.Any(e => e.Id == c.EquipmentId && e.UnitId == pageSensorDto.UnitId.Value))) // 测点挂在部件
                );
            }

            var totalCount = await AsyncExecuter.CountAsync(query);

            query = query.WhereIf(!string.IsNullOrEmpty(pageSensorDto.PointName),
                item => item.vibChannel.PointName.Contains(pageSensorDto.PointName));// 测点名过滤

            query = query.WhereIf(pageSensorDto.status.HasValue,
                item => item.SensorStatus == pageSensorDto.status.Value);// 传感器状态过滤

            if (pageSensorDto.IsPage)
            {
                query = query.PageBy(pageSensorDto.SkipCount, pageSensorDto.MaxResultCount);
            }

            var queryResult = await AsyncExecuter.ToListAsync(query);

            var result = new List<SensorResultDto>();
            foreach (var item in queryResult)
            {
                string unitName = null;
                Guid? unitId = null;

                // 根据 Point 的 OwnerType 和 OwnerId 确定机组信息
                switch (item.point.OwnerType)
                {
                    case nameof(Unit): // 测点挂在机组
                        var unit = unitQuery.FirstOrDefault(u => u.Id == item.point.OwnerId);
                        if (unit != null)
                        {
                            unitName = unit.Name;
                            unitId = unit.Id;
                        }
                        break;

                    case nameof(Equipment): // 测点挂在设备
                        var equipment = equipmentQuery.FirstOrDefault(e => e.Id == item.point.OwnerId);
                        if (equipment != null)
                        {
                            var parentUnit = unitQuery.FirstOrDefault(u => u.Id == equipment.UnitId);
                            if (parentUnit != null)
                            {
                                unitName = parentUnit.Name;
                                unitId = parentUnit.Id;
                            }
                        }
                        break;

                    case nameof(Component): // 测点挂在部件
                        var component = componentQuery.FirstOrDefault(c => c.Id == item.point.OwnerId);
                        if (component != null)
                        {
                            var parentEquipment = equipmentQuery.FirstOrDefault(e => e.Id == component.EquipmentId);
                            if (parentEquipment != null)
                            {
                                var parentUnit = unitQuery.FirstOrDefault(u => u.Id == parentEquipment.UnitId);
                                if (parentUnit != null)
                                {
                                    unitName = parentUnit.Name;
                                    unitId = parentUnit.Id;
                                }
                            }
                        }
                        break;
                }
                result.Add(new SensorResultDto
                {
                    UnitId = unitId,
                    UnitName = unitName,
                    PointId = item.vibChannel.PointId,
                    PointName = item.vibChannel.PointName,
                    CollectCode = item.sensor.CollectCode,
                    Value = item.sensor.CheckValue,
                    Status = item.SensorStatus.ToString(),
                    TotalCount = totalCount
                });
            }
            return result;
        }
    }
}
